package com.letu.database.mybatis.auth;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.toolkit.PluginUtils;
import com.baomidou.mybatisplus.extension.plugins.inner.InnerInterceptor;
import com.letu.annotation.database.mybatis.auth.DataScope;
import com.letu.annotation.database.mybatis.auth.DataScopeOfUserId;
import com.letu.annotation.database.mybatis.auth.DataScopeType;
import com.letu.core.context.ContextUtil;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.session.ResultHandler;
import org.apache.ibatis.session.RowBounds;

import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.function.Function;

/**
 * mybatis 数据权限拦截器
 * <p>
 * <p>
 * 1，全部：没有createdBy权限
 * 2，本级：当前用户的orgId
 * 3，本级以及子级
 * 4，自定义：
 * 5，个人：createdBy = 1
 *
 * @author ligang
 * @date 2020/9/27 10:00 上午
 */
@Slf4j
@AllArgsConstructor
public class DataScopeInnerInterceptor implements InnerInterceptor {
    private final Function<Long, DataScopeOfUserId> function;


    /**
     * 查找参数是否包括DataScope对象
     *
     * @param parameterObj 参数列表
     * @return DataScope
     */
    protected Optional<DataScope> findDataScope(Object parameterObj) {
        if (parameterObj == null) {
            return Optional.empty();
        }
        if (parameterObj instanceof DataScope) {
            return Optional.of((DataScope) parameterObj);
        } else if (parameterObj instanceof Map) {
            for (Object val : ((Map<?, ?>) parameterObj).values()) {
                if (val instanceof DataScope) {
                    return Optional.of((DataScope) val);
                }
            }
        }
        return Optional.empty();
    }

    /**
     *  操作前置处理
     * <p>
     * 改改sql啥的
     */
    @Override
    public void beforeQuery(Executor executor, MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) {
        DataScope dataScope = findDataScope(parameter).orElse(null);
        if (dataScope == null) {
            return;
        }
        Long userId = ContextUtil.getUserId();
        DataScopeOfUserId result = function.apply(userId);
        String originalSql = boundSql.getSql();

        DataScopeType dsType = DataScopeType.get(result.getDsType());
        //本人所属组能看到的用户
        String myRoleUserIds = CollectionUtil.join(result.getMyRoleUserIds(), ",");
        //指派能看到的资源数据
        String lookResourceIds = CollectionUtil.join(result.getLookResourceIds(), ",");
        //指派能看到的所属用户的数据
        String lookUserIds = CollectionUtil.join(result.getLookUserIds(), ",");
        //指派能编辑的资源数据
        String editResourceIds = CollectionUtil.join(result.getEditResourceIds(), ",");
        //指派能编辑的所属用户的数据
        String editUserIds = CollectionUtil.join(result.getEditUserIds(), ",");
        //查全部
        if (DataScopeType.ALL.eq(dsType)) {
            return;
        }
        //查所指资源
        StringBuilder lookResourceSql = new StringBuilder();
        if (StringUtils.isNotBlank(lookUserIds)) {
            lookResourceSql.append(" temp_data_scope.created_by in (" + lookUserIds + ")");
        }
        if (StringUtils.isNotBlank(lookResourceIds)) {
            if (lookResourceSql.length() > 0) {
                lookResourceSql.append(" or ");
            }
            lookResourceSql.append(" temp_data_scope.id in (" + lookResourceIds + ")");
        }

        //查个人
        if (DataScopeType.SELF.eq(dsType)) {
            originalSql = "select * from (" + originalSql + ") temp_data_scope where temp_data_scope.created_by" + " = " + userId;
        } else if (DataScopeType.ASSIGN_LEVEL.eq(dsType)) {
            //查所指组和人
            originalSql = "select * from (" + originalSql + ") temp_data_scope where " + lookResourceSql;
        } else if (DataScopeType.THIS_LEVEL.eq(dsType)) {
            //查本组
            originalSql = "select * from (" + originalSql + ") temp_data_scope where temp_data_scope.created_by in (" + myRoleUserIds + ") or " + lookResourceSql;
        } else if (DataScopeType.THIS_LEVEL_CHILDER.eq(dsType)) {
            //本组以及子组
            originalSql = "select * from (" + originalSql + ") temp_data_scope where temp_data_scope.created_by in (" + myRoleUserIds + ") or " + lookResourceSql;
        }

        PluginUtils.MPBoundSql mpBoundSql = PluginUtils.mpBoundSql(boundSql);
        mpBoundSql.sql(originalSql);
    }
}
